package com.wanqing.service.impl;

import ch.qos.logback.core.joran.util.beans.BeanUtil;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.wanqing.constant.JwtClaimsConstant;
import com.wanqing.constant.MessageConstant;
import com.wanqing.dto.UserLoginDTO;
import com.wanqing.entity.User;
import com.wanqing.exception.BaseException;
import com.wanqing.exception.LoginFailedException;
import com.wanqing.mapper.UserMapper;
import com.wanqing.properties.JwtProperties;
import com.wanqing.service.UserService;
import com.wanqing.utils.JwtUtil;
import com.wanqing.vo.UserLoginVO;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;


import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {
    //微信服务接口地址
    private static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";

    @Resource
    private UserMapper userMapper;
    @Autowired
    private Client client;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private JwtProperties jwtProperties;

    @Override
    public User wxLogin(UserLoginDTO userLoginDTO) {
        //调用微信接口服务，获得当前微信用户的openid
        String openid = getOpenid(userLoginDTO);
        //判断openid是否为空，如果为空，登录失败，抛出异常
        if (openid == null) {
            throw new LoginFailedException(MessageConstant.LOGIN_FAILED);
        }
        //判断当前用户是否为新用户
        User user = userMapper.getByOpenid(openid);
        //如果是新用户，则自动完成注册
        if (user == null) {
            user = User.builder().openid(openid).createTime(LocalDateTime.now()).build();
            userMapper.insert(user);
        }
        return user;
    }

    @Override
    public void getSMSCode(String phone) {
        //检查手机号是否为空
        if (!StringUtils.hasText(phone)) {
            throw new BaseException("手机号不能为空");
        }
        //检查redis中是否已经存在该手机号的key
        String key = JwtClaimsConstant.APP_LOGIN_PREFIX + phone;
        Boolean hasKey = redisTemplate.hasKey(key);
        if (Boolean.TRUE.equals(hasKey)) {
            //若存在，则检查其存在的时间
            Long expire = redisTemplate.getExpire(key, TimeUnit.SECONDS);
            if (JwtClaimsConstant.APP_LOGIN_CODE_TTL_SEC - expire < JwtClaimsConstant.APP_LOGIN_CODE_RESEND_TIME_SEC) {
                //若存在时间不足一分钟，响应发送过于频繁
                throw new BaseException("发送验证码过于频繁");
            }
        }
        //若不存在，生成验证码,并存入redis
        String code = getVerifyCode(6);
        sendCode(phone, code);
        redisTemplate.opsForValue().set(key, code, JwtClaimsConstant.APP_LOGIN_CODE_TTL_SEC, TimeUnit.SECONDS);
    }

    public String getVerifyCode(int length) {
        StringBuilder builder = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            builder.append(random.nextInt(10));
        }
        return builder.toString();
    }

    public void sendCode(String phone, String verifyCode) {
        // 创建发送短信请求对象
        SendSmsRequest smsRequest = new SendSmsRequest();

        // 设置短信签名名称
        smsRequest.setSignName("阿里云短信测试");

        // 设置短信模板代码
        smsRequest.setTemplateCode("SMS_154950909");

        // 设置接收短信的电话号码
        smsRequest.setPhoneNumbers(phone);

        // 设置短信模板参数，此处为验证码
        smsRequest.setTemplateParam("{\"code\":\"" + verifyCode + "\"}");

        // 尝试发送短信，如果发送失败则抛出运行时异常
        try {
            client.sendSms(smsRequest);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public UserLoginVO login(UserLoginDTO userLoginDTO) {
        //判断手机号和验证码是否为空
        if (!StringUtils.hasText(userLoginDTO.getPhone())) {
            throw new BaseException("手机号码为空");
        }
        if (!StringUtils.hasText(userLoginDTO.getCode())) {
            throw new BaseException("验证码为空");
        }
        //校验验证码
        String key = JwtClaimsConstant.APP_LOGIN_PREFIX + userLoginDTO.getPhone();
        String code = redisTemplate.opsForValue().get(key);
        if (code == null) {
            throw new BaseException("验证码已过期");
        }
        if (!code.equals(userLoginDTO.getCode())) {
            throw new BaseException("验证码错误");
        }
        //判断用户是否存在，不存在就注册
        User user = userMapper.getByPhone(userLoginDTO.getPhone());
        if (user == null) {
            user = new User();
            user.setPhone(userLoginDTO.getPhone());
            user.setNickname("用户-" + userLoginDTO.getPhone().substring(7, 11));
            user.setCreateTime(LocalDateTime.now());
            userMapper.insert(user);
        }
        //创建并返回token
        HashMap<String, Object> map = new HashMap<>();
        map.put("userId", user.getId());
        map.put("userName", user.getPhone());
        String token = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), map);
        UserLoginVO userLoginVO = new UserLoginVO();
        BeanUtils.copyProperties(user, userLoginVO);
        userLoginVO.setToken(token);
        return userLoginVO;
    }

    private String getOpenid(UserLoginDTO userLoginDTO) {
        // TODO: 2025/7/12 用户端登录待修改
        return "openid";
    }
}
